#include <linux/sem.h>
#include <linux/sched.h>
#include <unistd.h>
#include <asm/segment.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <linux/fdreg.h>
#include <asm/system.h>
#include <asm/io.h>


sem_t semt_able[SEM_TABLE_SIZE];
int Isused = 0;//标记是否使用过

sem_t* sys_sem_open(const char* name, unsigned int value)
{

    char kernelname[100]={0};   /* 应该足够大了 */
    int i = 0;
    int name_len = 0;
    
    /*初始化第一次使用table*/
    if (!Isused)
    {
        for (i = 0;i < SEM_TABLE_SIZE;i++)
        {
            semt_able[i].name[0] = '\0';
        }
        Isused = 1;
    }


    while (get_fs_byte(name + name_len) != '\0')
        name_len++;
    if (name_len > SEM_NAME_LEN)
        return NULL;
    for (i = 0;i < name_len;i++)
     /* 从用户态复制到内核态 */
        kernelname[i] = get_fs_byte(name + i);
   
    //printk("kernelname::%s\n",kernelname);
    
    sem_t* p = NULL;
    for (i = 0;i < SEM_TABLE_SIZE;i++)
    {
        if (semt_able[i].name[0] != '\0')
        {
            if (!strcmp(kernelname, semt_able[i].name))
            {
                p = &semt_able[i];

               // printk("find %d %s-value%d\n",i,p->name,p->value);
                return p;
            }
        }
        else if (!p)
        {
            //printk("creat %d ",i);
            p = &semt_able[i];
        }

    }
    
    if (p)
    {
        i = 0;
        for (i = 0;i < name_len;i++)
        {
            p->name[i] = kernelname[i];
        }
        p->name[i+1]='\0';
        p->value = value;
        p->queue=NULL;
    }
   // printk("%s-value %d\n",p->name,p->value);
    return p;
}


int sys_sem_wait(sem_t* sem)
{
    cli();
    while (sem->value <= 0)        //使得所有小于0的进程阻塞
        sleep_on(&(sem->queue));
    sem->value--;
    sti();
    return 0;
}
int sys_sem_post(sem_t* sem)
{
    cli();
    sem->value++;
    if ((sem->value) <= 1)    //小于0阻塞，只有为1时才唤醒，保证一次仅唤醒一个进程
        wake_up(&(sem->queue));
    sti();
    return 0;
}

int sys_sem_unlink(const char* name)
{
    char kernelname[100]={0};   /* 应该足够大了 */
    int i = 0;
    int name_len = 0;

    /*计算长度*/
    while (get_fs_byte(name + name_len) != '\0')
        name_len++;

    if (name_len > SEM_NAME_LEN)
        return NULL;

    for (i = 0;i < name_len;i++)
        kernelname[i] = get_fs_byte(name + i);


    sem_t *p=NULL;

    for (i = 0;i < SEM_TABLE_SIZE;i++)
    {
        if (semt_able[i].name[0] != '\0')
        {
            if (!strcmp(kernelname, semt_able[i].name))
            {
                p = &semt_able[i];
                break;
            }
        }
    }
    if (p)
    {
        p->name[0]='\0';
        return 0;
    }
    else
        return -1;
}
